home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 July: Mac OS SDK / Dev.CD Jul 00 SDK2.toast / Development Kits / Hardware / Mac OS USB DDK / Mac OS USB DDK 1.4.1 / Examples / USBSampleStorageDriver / UnitTableDriver / USB_ManualEjectSupport.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-04-25  |  5.1 KB  |  231 lines  |  [TEXT/CWIE]

  1. /*
  2.     File:        USB_ManualEjectSupport.c
  3.  
  4.     Contains:    All support for handling manual ejectable media.
  5.  
  6.     Version:    1.0
  7.  
  8.     Copyright:    © 1999-2000 by Apple Computer, Inc., all rights reserved.
  9. */
  10.  
  11. #include "USB_ManualEjectSupport.h"
  12.  
  13. #include <DriverServices.h>
  14.  
  15. #include "USB_ShimServicesSupport.h"
  16. #include "USB_StdCommands.h"
  17. #include "StorageDeviceConfiguration.h"
  18.  
  19. extern UInt8 gDeviceUSBSubClass;
  20.  
  21. #pragma mark --
  22. #pragma mark Manual Eject Check
  23.  
  24. Boolean IsDeviceKnownManualEject( void )
  25. {
  26.     Boolean result;
  27.     
  28.     if ( gDeviceUSBSubClass == kUSBStorageUFISubclass )
  29.     {
  30.         result = true;
  31.     }
  32.     else
  33.     {
  34.         // Get this information from the Device Info header
  35.         result = kDeviceIsManualEject;
  36.     }
  37.  
  38.     return result;
  39. }
  40.  
  41. // These are all routines for handling the Manual Eject Check
  42. static Boolean    MaintainManualEjectInterrupt = false;
  43. static Boolean    gManualEjectRemoveIssued = false;
  44. static volatile Boolean    InManualEjectCheckInterrupt = false;
  45. static TimerID    ManualEjectInterruptTimer = 0;
  46. static OSStatus ManualEjectCheckInterrupt( void *p1, void *p2);
  47.  
  48. // Accessors for Manual Eject Media Removed 
  49. Boolean WasManualEjectRemoveIssued( void )
  50. {
  51.     return gManualEjectRemoveIssued;
  52. }
  53.  
  54. void SetManualEjectRemoveIssued( void )
  55. {
  56.     gManualEjectRemoveIssued = true;
  57. }
  58.  
  59. void ClearManualEjectRemoveIssued( void )
  60. {
  61.     gManualEjectRemoveIssued = false;
  62. }
  63.  
  64. // Accessors for In Manual Eject Interrupt flag
  65. void SetInManualEjectCheckInterrupt( void )
  66. {
  67.     InManualEjectCheckInterrupt = true;
  68. }
  69.  
  70. void ClearInManualEjectCheckInterrupt( void )
  71. {
  72.     InManualEjectCheckInterrupt = false;
  73. }
  74.  
  75. // Accessors for turning the manual eject check on and off
  76. Boolean GetMaintainManualEjectInterrupt( void )
  77. {
  78.     return MaintainManualEjectInterrupt;
  79. }
  80.  
  81. void SetManualCheckInterrupt( void )
  82. {
  83.     gManualEjectRemoveIssued = false;
  84.     MaintainManualEjectInterrupt = true;
  85.     ResetManualEjectInterrupt();
  86. }
  87.  
  88. void ClearManualEjectInterrupt( void )
  89. {
  90.     MaintainManualEjectInterrupt = false;
  91.     CancelManualEjectInterrupt();
  92. }
  93.  
  94. void ResetManualEjectInterrupt( void )
  95. {
  96.     AbsoluteTime        theWait;
  97.  
  98.     // If there is an outstanding timer, cancel it
  99.     CancelManualEjectInterrupt();
  100.  
  101.     // If we are maintaining an interrupt, set it now
  102.     if (( MaintainManualEjectInterrupt == true ) && (InManualEjectCheckInterrupt == false))
  103.     {
  104.         // This is set to 5 seconds to collision problems with
  105.         // commands that occur during hot-unplugging.  This is only
  106.         // a temporary fix and should be redesigned for Greyhound 1.4
  107. /*        theWait = DurationToAbsolute(durationSecond*5);*/
  108.         theWait = DurationToAbsolute(durationSecond);
  109.         theWait = AddAbsoluteToAbsolute(UpTime(), theWait);
  110.         SetInterruptTimer( &theWait, &ManualEjectCheckInterrupt, nil, &ManualEjectInterruptTimer);
  111.     }
  112. }
  113.  
  114. void CancelManualEjectInterrupt( void )
  115. {
  116.     if( ManualEjectInterruptTimer != nil )
  117.     {
  118.         AbsoluteTime    timeLeft;
  119.         
  120.         // Cancel any pending timers
  121.         CancelTimer( ManualEjectInterruptTimer, &timeLeft);
  122.         ManualEjectInterruptTimer = 0;
  123.     }
  124. }
  125.  
  126. enum
  127. {
  128.     kEjectCheckStartState = 0,
  129.     kEjectCheckTURDone,
  130.     kEjectCheckReqSenseDone
  131. };
  132.  
  133. static void ManualEjectCheckStateMachine(  IntDriveRequestPBPtr requestPB  );
  134.  
  135. OSStatus ManualEjectCheckInterrupt( void *p1, void *p2)
  136. {
  137. #pragma unused ( p1, p2 )
  138.     IntDriveRequestPB    *ourPB;
  139.  
  140.     ManualEjectInterruptTimer = 0;
  141.     
  142.     if ( MaintainManualEjectInterrupt == false ) 
  143.     {
  144.         return noErr;
  145.     }
  146.     
  147.     if ( IsCommandPending() == false )
  148.     {
  149.         // Only perform the check when there is no command pending
  150.         ourPB = GetManualEjectPB();
  151.         if ( ourPB == nil )
  152.         {
  153.             ResetManualEjectInterrupt();
  154.             return noErr;
  155.         }
  156.         
  157.         ourPB->currentExecutionState = kEjectCheckStartState;
  158.         ourPB->completionProc = &ManualEjectCheckStateMachine;
  159.         ManualEjectCheckStateMachine( ourPB );
  160.     }
  161.     else
  162.     {
  163.         ResetManualEjectInterrupt();
  164.     }
  165.     
  166.     return noErr;
  167. }
  168.  
  169. void ManualEjectCheckStateMachine(  IntDriveRequestPBPtr requestPB  )
  170. {
  171.     OSStatus             err = requestPB->status;
  172.     Boolean                resetTheInterrupt = false;
  173.  
  174.     if ( MaintainManualEjectInterrupt == false ) 
  175.     {    
  176.         FreeManualEjectPB( requestPB );
  177.         return;
  178.     }
  179.  
  180.     switch( requestPB->currentExecutionState )
  181.     {
  182.         case kEjectCheckStartState:
  183.         {
  184.             // Let's do a TUR and Request sense to make sure the drive is in
  185.             // a good state
  186.             InManualEjectCheckInterrupt = true;
  187.             requestPB->currentExecutionState = kEjectCheckTURDone;
  188.             requestPB->completionProc = &ManualEjectCheckStateMachine;
  189.             err = TestUnitReadyBuilder( requestPB );
  190.         }
  191.         break;
  192.         
  193.         case kEjectCheckTURDone:
  194.         {
  195.             requestPB->currentExecutionState = kEjectCheckReqSenseDone;
  196.             requestPB->completionProc = &ManualEjectCheckStateMachine;
  197.             err = RequestSenseBuilder( requestPB, (Ptr) requestPB->buffer );
  198.         }
  199.         break;
  200.         
  201.         case kEjectCheckReqSenseDone:
  202.         {
  203.             if ( err == noErr )
  204.             {
  205.                 if((requestPB->buffer[12] == 0x28) || (requestPB->buffer[12] == 0x3A))
  206.                 {
  207.                     // The Disk has been removed, ask for it back
  208.                     gManualEjectRemoveIssued = true;
  209.                     InManualEjectCheckInterrupt = false;
  210.                     FreeManualEjectPB( requestPB );
  211.                     CancelManualEjectInterrupt();
  212.                     SendMediaWasRemovedEvent();
  213.                     return;
  214.                 }
  215.             }
  216.  
  217.             // Reset the Interrupt
  218.             resetTheInterrupt = true;
  219.         }
  220.         break;
  221.     }
  222.     
  223.     if (( resetTheInterrupt == true ) || (err != kRequestPending))
  224.     {
  225.         FreeManualEjectPB( requestPB );
  226.         InManualEjectCheckInterrupt = false;
  227.         ResetManualEjectInterrupt();
  228.     }
  229. }
  230.  
  231.